package com.example.demo;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import tbs.framework.annotations.MethodIntercept;
import tbs.framework.async.task.annotations.AsyncTaskId;
import tbs.framework.async.task.annotations.AsyncWithCallback;
import tbs.framework.cache.annotations.CacheLoading;
import tbs.framework.cache.annotations.CacheUnloading;
import tbs.framework.constants.BeanNameConstant;
import tbs.framework.lock.annotations.LockIt;
import tbs.framework.lock.expections.ObtainLockFailException;
import tbs.framework.log.ILogger;
import tbs.framework.log.annotations.AutoLogger;
import tbs.framework.multilingual.annotations.Translated;
import tbs.framework.utils.LockUtils;
import tbs.framework.utils.wrapper.LockWrapper;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;

@Component
public class AsyncTest {

    @AutoLogger
    private ILogger logger;


    public AsyncTest() {

    }

    private static final String READ = "read", WRITE = "write";

//    @Resource
//    IReadWriteLock simpleReadWriteLock;
//
//    int r = 0;
//
//    public int testRead() throws InterruptedException {
//
//        logger.info("reading ...");
//        int v = -1;
//        simpleReadWriteLock.readLock().tryLock(Duration.ofMinutes(1));
//        //        read.lock();
//        v = r;
//        //        read.unlock();
//        simpleReadWriteLock.readLock().unLock();
//        logger.info("read end");
//        return v;
//    }
//
//    public void testWrite() throws InterruptedException {
//        logger.info("writing ...");
//        simpleReadWriteLock.writeLock().tryLock(Duration.ofMinutes(1));
//        //        write.lock();
//        r++;
//        //        write.unlock();
//        simpleReadWriteLock.writeLock().unLock();
//        logger.info("write end");
//    }

    @MethodIntercept(LogMethodIntercept.class)
    @CacheUnloading(key = "#method.#args[0]", intArgs = 20000)
    @CacheLoading(key = "#method.#args[0]")
    public String testCache(int id) throws InterruptedException {
        Thread.currentThread().join(1000);
        return "hello world";
    }

    @Async(BeanNameConstant.ASYNC_EXECUTOR)
    public Future test() {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return LockWrapper.getInstance().wrapSafely((a) -> {
                    this.logger.info("start wait");
                    try {
                        Thread.currentThread().join(1000);
                    } catch (final InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    this.logger.info("end onece");
                    return "Hello World!";
                }, null, LockUtils.getInstance().getLock(this), null);
            } catch (final ObtainLockFailException e) {
                throw new RuntimeException(e);
            } catch (final Throwable throwable) {
                throw new RuntimeException(throwable);
            }
        });
    }

    @LockIt
    @AsyncWithCallback
    public String test1(@AsyncTaskId String id) throws ObtainLockFailException, InterruptedException {
        Integer[] v = new Integer[] {0};
        Thread.currentThread().join(1500);
        for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 200; j++) {
                        logger.info("value :{}", v[0]++);
                }
        }

        return null;

    }

    @Translated
    public TestModel testModel(String text) {
        return new TestModel(text);
    }
}
